home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Id: sashimi.c 1.6 1998/09/11 22:03:36 olsen Exp olsen $
- *
- * Sashimi -- intercepts raw serial debugging output on your own machine
- *
- * Written by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
- * Public Domain
- *
- * :ts=4
- */
-
- #include <exec/memory.h>
-
- #include <devices/timer.h>
-
- #include <dos/dosextens.h>
- #include <dos/rdargs.h>
-
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
-
- #include <pragmas/exec_sysbase_pragmas.h>
- #include <pragmas/dos_pragmas.h>
-
- #include <string.h>
- #include <stdio.h>
-
- /****************************************************************************/
-
- STRPTR Version = "$VER: Sashimi 1.4 (11.9.98)\r\n";
-
- /****************************************************************************/
-
- #define OK (0)
- #define NOT !
- #define BUSY NULL
-
- /****************************************************************************/
-
- #define MILLION 1000000
-
- /****************************************************************************/
-
- extern struct Library * SysBase;
- extern struct Library * DOSBase;
-
- /****************************************************************************/
-
- typedef LONG SWITCH;
- typedef LONG * NUMBER;
- typedef STRPTR KEY;
-
- struct
- {
- /* Startup options */
- SWITCH On; /* Ignored */
- NUMBER BufferK; /* Buffer size, to the power of two */
- NUMBER BufferSize; /* Buffer size in bytes */
- SWITCH NoPrompt; /* Do not show the initial prompt message */
- SWITCH Quiet; /* Do not produce any output at all */
- SWITCH AskExit; /* Ask whether to exit the program */
- SWITCH AskSave; /* Ask for a file to save the buffer to when exiting */
- SWITCH TimerOn; /* Check the ring buffer every 1/10 of a second */
- SWITCH Console; /* Open a console window for I/O */
- KEY Window; /* Console window specifier */
-
- /* Runtime options */
- SWITCH Off; /* Turn Sashimi off */
- SWITCH Save; /* Save the ring buffer contents */
- KEY SaveAs; /* Save the ring buffer contents under a specific name */
- SWITCH Empty; /* Empty the ring buffer */
- } ShellArguments;
-
- const STRPTR ShellTemplate = "ON/S,BUFK/N,BUFFERSIZE/N,NOPROMPT/S,QUIET/S,ASKEXIT/S,"
- "ASKSAVE/S,TIMERON/S,CONSOLE/S,WINDOW/K,"
- "OFF/S,SAVE/S,SAVEAS/K,EMPTY/S";
-
- /****************************************************************************/
-
- struct SashimiResource
- {
- struct Library sr_Library; /* Global link */
-
- struct Task * sr_Owner; /* Current owner of the patches */
- LONG sr_OwnerSigBit;
- ULONG sr_OwnerSigMask; /* Signal mask to send when a new line is in the buffer. */
-
- UBYTE * sr_FIFO; /* The message buffer */
- ULONG sr_FIFOTotalSize; /* Number of bytes allocated for the buffer */
- ULONG sr_FIFOReadIndex; /* Read index counter */
- ULONG sr_FIFOWriteIndex; /* Write index counter */
- ULONG sr_FIFOBytesStored; /* Number of bytes in the FIFO */
- BOOL sr_FIFOOverrun; /* TRUE if the write index counter has
- * overrun the read index counter.
- */
- BOOL sr_FIFOWrapped; /* TRUE if the write index counter has
- * wrapped around the ring buffer.
- */
- };
-
- struct SashimiResource * SashimiResource;
- const STRPTR SashimiResourceName = "sashimi.resource";
-
- /****************************************************************************/
-
- extern LONG __far LVORawIOInit;
- extern LONG __far LVORawMayGetChar;
- extern LONG __far LVORawPutChar;
-
- /****************************************************************************/
-
- APTR OldRawIOInit;
- APTR OldRawMayGetChar;
- APTR OldRawPutChar;
-
- /****************************************************************************/
-
- VOID __saveds __asm
- NewRawIOInit(VOID)
- {
- }
-
- LONG __saveds __asm
- NewRawMayGetChar(VOID)
- {
- return('y');
- }
-
- /****************************************************************************/
-
- extern VOID __asm SafeRawPutChar(register __d0 UBYTE c);
-
- VOID __saveds __asm
- NewRawPutChar(register __d0 UBYTE c)
- {
- /* Do not store NUL bytes. */
- if(c != '\0')
- {
- STATIC ULONG Position = 0;
-
- /* Filter out extra <cr> characters. */
- if(c != '\r' || Position > 0)
- {
- struct SashimiResource * sr = SashimiResource;
-
- /* Store another byte in the buffer */
- sr->sr_FIFO[sr->sr_FIFOWriteIndex] = c;
- sr->sr_FIFOWriteIndex = (sr->sr_FIFOWriteIndex + 1) % sr->sr_FIFOTotalSize;
-
- /* Check if the ring buffer was overrun */
- sr->sr_FIFOBytesStored++;
- if(sr->sr_FIFOBytesStored >= sr->sr_FIFOTotalSize)
- {
- sr->sr_FIFOOverrun = TRUE;
-
- /* Move the read index to the same position as
- * the write index.
- */
- sr->sr_FIFOReadIndex = sr->sr_FIFOWriteIndex;
- }
-
- /* If the buffer wraps around, remember it. */
- if(sr->sr_FIFOWriteIndex == 0)
- sr->sr_FIFOWrapped = TRUE;
-
- /* Notify Sashimi every time there is an end of line
- * character in the stream.
- */
- if(c == '\n' || c == '\r')
- Signal(sr->sr_Owner,sr->sr_OwnerSigMask);
- }
-
- if(c == '\r' || c == '\n')
- Position = 0;
- else
- Position++;
- }
- }
-
- /****************************************************************************/
-
- VOID
- RemovePatches(VOID)
- {
- APTR res;
-
- /* We disable the interrupts because the raw I/O routines can
- * be called from within interrupt code.
- */
- Disable();
-
- /* For every patch planted, remove it and check whether the code
- * had been patched before. If it has, restore the patch. Note that
- * this is not bullet proof :(
- */
- res = SetFunction(SysBase,(LONG)&LVORawIOInit,(ULONG (*)())OldRawIOInit);
- if(res != (APTR)NewRawIOInit)
- SetFunction(SysBase,(LONG)&LVORawIOInit,(ULONG (*)())res);
-
- res = SetFunction(SysBase,(LONG)&LVORawMayGetChar,(ULONG (*)())OldRawMayGetChar);
- if(res != (APTR)NewRawMayGetChar)
- SetFunction(SysBase,(LONG)&LVORawMayGetChar,(ULONG (*)())res);
-
- res = SetFunction(SysBase,(LONG)&LVORawPutChar,(ULONG (*)())OldRawPutChar);
- if(res != (APTR)SafeRawPutChar)
- SetFunction(SysBase,(LONG)&LVORawPutChar,(ULONG (*)())res);
-
- Enable();
- }
-
- VOID
- InstallPatches(VOID)
- {
- /* We disable the interrupts because the raw I/O routines can
- * be called from within interrupt code.
- */
- Disable();
-
- OldRawIOInit = SetFunction(SysBase,(LONG)&LVORawIOInit, (ULONG (*)())NewRawIOInit);
- OldRawMayGetChar = SetFunction(SysBase,(LONG)&LVORawMayGetChar, (ULONG (*)())NewRawMayGetChar);
- OldRawPutChar = SetFunction(SysBase,(LONG)&LVORawPutChar, (ULONG (*)())SafeRawPutChar);
-
- Enable();
- }
-
- /****************************************************************************/
-
- VOID
- FreeSashimiResource(struct SashimiResource * resource)
- {
- if(resource != NULL)
- {
- FreeSignal(resource->sr_OwnerSigBit);
-
- FreeVec(resource->sr_FIFO);
- FreeVec(resource);
- }
- }
-
- LONG
- RemoveSashimiResource(struct SashimiResource * resource)
- {
- LONG error = OK;
-
- if(resource != NULL)
- {
- Forbid();
-
- /* Allow the resource to be removed only if
- * there are no customers using it.
- */
- if(resource->sr_Library.lib_OpenCnt == 0)
- {
- RemResource(resource);
- }
- else
- {
- error = ERROR_OBJECT_IN_USE;
- }
-
- Permit();
- }
-
- return(error);
- }
-
- LONG
- AddSashimiResource(ULONG bufferSize,struct SashimiResource ** resourcePtr)
- {
- struct SashimiResource * resource;
- LONG error = OK;
-
- resource = AllocVec(sizeof(*resource),MEMF_ANY|MEMF_CLEAR|MEMF_PUBLIC);
- if(resource != NULL)
- {
- resource->sr_Library.lib_Node.ln_Name = (char *)SashimiResourceName;
- resource->sr_Library.lib_Node.ln_Type = NT_RESOURCE;
- resource->sr_Owner = FindTask(NULL);
- resource->sr_FIFOTotalSize = bufferSize;
-
- resource->sr_OwnerSigBit = AllocSignal(-1);
- if(resource->sr_OwnerSigBit != -1)
- {
- resource->sr_OwnerSigMask = (1UL << resource->sr_OwnerSigBit);
-
- resource->sr_FIFO = AllocVec(resource->sr_FIFOTotalSize,MEMF_ANY|MEMF_PUBLIC);
- if(resource->sr_FIFO != NULL)
- {
- Forbid();
-
- /* Do not add the resource if it has already been installed. */
- if(OpenResource((STRPTR)SashimiResourceName) == NULL)
- {
- AddResource(resource);
- }
- else
- {
- error = ERROR_OBJECT_EXISTS;
- }
-
- Permit();
- }
- else
- {
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- error = ERROR_NO_FREE_STORE;
- }
-
- if(error != OK)
- {
- FreeSashimiResource(resource);
- resource = NULL;
- }
-
- *resourcePtr = resource;
-
- return(error);
- }
-
- /****************************************************************************/
-
- VOID
- CloseSashimiResource(struct SashimiResource * resource)
- {
- if(resource != NULL)
- {
- Forbid();
-
- resource->sr_Library.lib_OpenCnt--;
-
- Permit();
- }
- }
-
- struct SashimiResource *
- OpenSashimiResource(VOID)
- {
- struct SashimiResource * resource;
-
- Forbid();
-
- resource = OpenResource((STRPTR)SashimiResourceName);
- if(resource != NULL)
- {
- resource->sr_Library.lib_OpenCnt++;
- }
-
- Permit();
-
- return(resource);
- }
-
- /****************************************************************************/
-
- VOID
- EmptyBuffer(struct SashimiResource * resource)
- {
- Disable();
-
- resource->sr_FIFOReadIndex = 0;
- resource->sr_FIFOWriteIndex = 0;
- resource->sr_FIFOBytesStored = 0;
- resource->sr_FIFOOverrun = FALSE;
- resource->sr_FIFOWrapped = FALSE;
-
- Enable();
- }
-
- LONG
- SaveBuffer(const STRPTR name,struct SashimiResource * resource)
- {
- STRPTR bufferCopy;
- LONG totalSize;
- LONG error = OK;
-
- totalSize = resource->sr_FIFOTotalSize;
-
- /* We allocate a temporary buffer to store the ring
- * buffer data in.
- */
- bufferCopy = AllocVec(totalSize,MEMF_ANY|MEMF_PUBLIC);
- if(bufferCopy != NULL)
- {
- BOOL wrapped;
- BOOL overrun;
- LONG writeIndex;
- LONG bytesInBuffer;
- BPTR file;
-
- /* Halt multitasking for a tick. */
- Forbid();
-
- wrapped = resource->sr_FIFOWrapped;
- overrun = resource->sr_FIFOOverrun;
-
- /* The index counter indicates how many bytes
- * have been written to the ring buffer, unless
- * the buffer index has wrapped around already.
- */
- writeIndex = bytesInBuffer = resource->sr_FIFOWriteIndex;
-
- /* If the buffer index has wrapped around, then
- * the entire buffer is filled with data.
- */
- if(wrapped)
- bytesInBuffer = totalSize;
-
- /* Make a copy of the current buffer contents. */
- if(bytesInBuffer > 0)
- {
- /* For a wrapped buffer, "unfold" the FIFO. */
- if(writeIndex < bytesInBuffer && wrapped)
- {
- /* Store the oldest buffer contents first. */
- CopyMem(resource->sr_FIFO + writeIndex,bufferCopy,bytesInBuffer - writeIndex);
-
- /* Add the most recent data. */
- CopyMem(resource->sr_FIFO,bufferCopy + bytesInBuffer - writeIndex,writeIndex);
- }
- else
- {
- CopyMem(resource->sr_FIFO,bufferCopy,bytesInBuffer);
- }
- }
-
- /* Enable multitasking again. */
- Permit();
-
- /* Write the buffer contents. */
- file = Open((STRPTR)name,MODE_NEWFILE);
- if(file != NULL)
- {
- if(overrun)
- {
- if(FPrintf(file,"BUFFER WAS OVERRUN - Data may have been lost\n") < 0)
- error = IoErr();
- }
-
- if(error == OK && wrapped)
- {
- if(FPrintf(file,"BUFFER WRAPPED - This is the most recent captured data\n\n") < 0)
- error = IoErr();
- }
-
- /* FPrintf() is a buffered I/O routine, this is why we need to flush the
- * output buffer here. Otherwise, it would be flushed after the Write()
- * command below is finished and the file is closed. This is not what
- * we want as that would have the effect of adding the messages above
- * to the end of the file.
- */
- if(error == OK)
- {
- Flush(file);
- }
-
- if(error == OK && bytesInBuffer > 0)
- {
- if(Write(file,bufferCopy,bytesInBuffer) != bytesInBuffer)
- error = IoErr();
- }
-
- Close(file);
- }
- else
- {
- error = IoErr();
- }
-
- FreeVec(bufferCopy);
- }
- else
- {
- error = ERROR_NO_FREE_STORE;
- }
-
- return(error);
- }
-
- /****************************************************************************/
-
- int
- main(int argc,char **argv)
- {
- int result = RETURN_FAIL;
-
- /* Kickstart 2.04 and a Shell window are required. */
- if(DOSBase->lib_Version >= 37 && argc > 0)
- {
- struct RDArgs * rdargs;
-
- rdargs = ReadArgs((STRPTR)ShellTemplate,(LONG *)&ShellArguments,NULL);
- if(rdargs != NULL)
- {
- struct SashimiResource * resource;
- struct MsgPort * timePort = NULL;
- struct timerequest * timeRequest = NULL;
- BOOL added = FALSE;
- BOOL opened = FALSE;
- LONG error = OK;
- BPTR oldOutput = NULL;
- BPTR newOutput = NULL;
- BPTR oldInput = NULL;
- BPTR newInput = NULL;
- struct MsgPort * oldConsoleTask = NULL;
- STRPTR saveFile;
-
- /* Fill in the save file name, we might need it later. */
- if(ShellArguments.SaveAs != NULL)
- saveFile = ShellArguments.SaveAs;
- else
- saveFile = "T:sashimi.out";
-
- /* Try to open the resource, and if that fails, create one. */
- resource = OpenSashimiResource();
- if(resource != NULL)
- {
- opened = TRUE;
- }
- else
- {
- ULONG bufferSize;
-
- /* The default buffer size is 32K. */
- bufferSize = 32 * 1024;
-
- /* Check for a specific buffer size (power of two). */
- if(ShellArguments.BufferK != NULL)
- bufferSize = 1024 * (*ShellArguments.BufferK);
-
- /* Check for a specific buffer size. */
- if(ShellArguments.BufferSize != NULL)
- bufferSize = (ULONG)(*ShellArguments.BufferSize);
-
- /* Don't make the buffer too small. */
- if(bufferSize < 4096)
- bufferSize = 4096;
-
- /* Add the resource to the public list. Note that
- * the patches are not installed yet.
- */
- error = AddSashimiResource(bufferSize,&resource);
- if(error == OK)
- {
- added = TRUE;
-
- /* Check if we should periodically check
- * the ring buffer.
- */
- if(ShellArguments.TimerOn)
- {
- error = ERROR_NO_FREE_STORE;
-
- /* Set up the timer.device interface. */
- timePort = CreateMsgPort();
- if(timePort != NULL)
- {
- timeRequest = (struct timerequest *)CreateIORequest(timePort,sizeof(*timeRequest));
- if(timeRequest != NULL)
- {
- if(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)timeRequest,0) == OK)
- error = OK;
- }
- }
- }
- }
- }
-
- /* Did we get everything we wanted? */
- if(error != OK)
- {
- PrintFault(error,"Sashimi");
- result = RETURN_ERROR;
- }
- else
- {
- if(opened)
- {
- /* Save the current ring buffer contents? */
- if(ShellArguments.SaveAs != NULL || ShellArguments.Save)
- {
- LONG error;
-
- error = SaveBuffer(saveFile,resource);
- if(error == OK)
- Printf("Sashimi buffer saved as \"%s\".\n",saveFile);
- else
- PrintFault(error,saveFile);
- }
-
- /* Empty the ring buffer? */
- if(ShellArguments.Empty)
- {
- EmptyBuffer(resource);
-
- Printf("Sashimi buffer cleared.\n");
- }
-
- /* Turn off Sashimi? */
- if(ShellArguments.Off)
- {
- struct Task * owner;
-
- Forbid();
-
- /* We cannot tell Sashimi to quit
- * if there is a single customer
- * left, such as us. This is why
- * we close the resource and
- * signal Sashimi to quit.
- */
- owner = resource->sr_Owner;
- CloseSashimiResource(resource);
- resource = NULL;
-
- Signal(owner,SIGBREAKF_CTRL_C);
-
- Permit();
- }
- }
-
- if(added)
- {
- ULONG signalsReceived,signalsToWaitFor;
- BOOL done;
-
- /* Open a console window? */
- if(ShellArguments.Console)
- {
- STRPTR consoleWindow;
- LONG error = OK;
-
- if(ShellArguments.Window != NULL)
- consoleWindow = ShellArguments.Window;
- else
- consoleWindow = "CON:0/20/640/100/Sashimi [Ctrl]+E=Empty [Ctrl]+F=File [Ctrl]+D=Reset console/AUTO/CLOSE/WAIT/INACTIVE";
-
- /* Open the window and make it the default
- * I/O stream.
- */
- newInput = Open(consoleWindow,MODE_NEWFILE);
- if(newInput != NULL)
- {
- oldConsoleTask = SetConsoleTask(((struct FileHandle *)BADDR(newInput))->fh_Type);
- newOutput = Open("CONSOLE:",MODE_OLDFILE);
- if(newOutput != NULL)
- {
- oldInput = SelectInput(newInput);
- oldOutput = SelectOutput(newOutput);
- }
- else
- {
- error = IoErr();
-
- /* Return to the original console task. */
- SetConsoleTask(oldConsoleTask);
- oldConsoleTask = NULL;
- }
- }
- else
- {
- error = IoErr();
- }
-
- if(error != OK)
- PrintFault(error,consoleWindow);
- }
-
- /* Show the banner message. */
- if(NOT ShellArguments.NoPrompt && NOT ShellArguments.Quiet)
- {
- struct Process * cli = (struct Process *)FindTask(NULL);
- LONG maxCli,thisCli = 1,i;
-
- /* Find our current CLI process number. */
- maxCli = MaxCli();
- for(i = 1 ; i <= maxCli ; i++)
- {
- if(FindCliProc(i) == cli)
- {
- thisCli = i;
- break;
- }
- }
-
- Printf("Sashimi installed ([Ctrl]+C or \"Break %ld\" to remove)\n",thisCli);
- }
-
- SashimiResource = resource;
- InstallPatches();
-
- signalsToWaitFor = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D |
- SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F |
- resource->sr_OwnerSigMask;
-
- /* Start the timer. */
- if(timePort != NULL)
- {
- signalsToWaitFor |= (1UL << timePort->mp_SigBit);
-
- timeRequest->tr_node.io_Command = TR_ADDREQUEST;
- timeRequest->tr_time.tv_secs = 0;
- timeRequest->tr_time.tv_micro = MILLION / 10;
-
- SendIO((struct IORequest *)timeRequest);
- }
-
- done = FALSE;
- do
- {
- signalsReceived = Wait(signalsToWaitFor);
-
- /* Check if we should test the buffer. */
- if(timePort != NULL)
- {
- if(signalsReceived & (1UL << timePort->mp_SigBit))
- {
- signalsReceived |= resource->sr_OwnerSigMask;
-
- WaitIO((struct IORequest *)timeRequest);
-
- /* Restart the timer. */
- timeRequest->tr_node.io_Command = TR_ADDREQUEST;
- timeRequest->tr_time.tv_secs = 0;
- timeRequest->tr_time.tv_micro = MILLION / 10;
-
- SendIO((struct IORequest *)timeRequest);
- }
- }
-
- /* Check if we should test the buffer. */
- if(signalsReceived & resource->sr_OwnerSigMask)
- {
- if(NOT ShellArguments.Quiet)
- {
- struct SashimiResource * sr = SashimiResource;
- UBYTE localBuffer[256];
- LONG filled = 0;
-
- /* Try to empty the ring buffer. */
- while(sr->sr_FIFOBytesStored > 0)
- {
- /* Read the next byte. */
- localBuffer[filled++] = sr->sr_FIFO[sr->sr_FIFOReadIndex];
-
- sr->sr_FIFOBytesStored--;
- sr->sr_FIFOReadIndex = (sr->sr_FIFOReadIndex + 1) % sr->sr_FIFOTotalSize;
-
- /* Has the buffer been filled to the brim? */
- if(filled == sizeof(localBuffer))
- {
- ULONG moreSignals;
-
- /* Check if there is a message for us. */
- moreSignals = SetSignal(0,SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F);
-
- /* Save the ring buffer to a file? */
- if(moreSignals & SIGBREAKF_CTRL_F)
- {
- LONG error;
-
- error = SaveBuffer(saveFile,resource);
- if(error == OK)
- Printf("Sashimi buffer saved as \"%s\".\n",saveFile);
- else
- PrintFault(error,saveFile);
- }
-
- /* Empty the ring buffer? */
- if(moreSignals & SIGBREAKF_CTRL_E)
- {
- EmptyBuffer(resource);
-
- Printf("Sashimi buffer cleared.\n");
- }
-
- /* Stop Sashimi? */
- if(moreSignals & SIGBREAKF_CTRL_C)
- {
- signalsReceived |= SIGBREAKF_CTRL_C;
-
- filled = 0;
- break;
- }
-
- /* Write the buffer to the file. */
- Write(Output(),localBuffer,filled);
- filled = 0;
- }
- }
-
- /* Store the remaining buffer contents. */
- if(filled > 0)
- {
- Write(Output(),localBuffer,filled);
- }
- }
- }
-
- /* Save current buffer to file. */
- if(signalsReceived & SIGBREAKF_CTRL_F)
- {
- LONG error;
-
- error = SaveBuffer(saveFile,resource);
- if(error == OK)
- {
- Printf("Sashimi buffer saved as \"%s\".\n",saveFile);
- }
- else
- {
- PrintFault(error,saveFile);
- }
- }
-
- /* Empty the buffer. */
- if(signalsReceived & SIGBREAKF_CTRL_E)
- {
- EmptyBuffer(resource);
-
- Printf("Sashimi buffer cleared.\n");
- }
-
- /* Reset the terminal. */
- if(signalsReceived & SIGBREAKF_CTRL_D)
- {
- Printf("\033c");
- Flush(Output());
- }
-
- /* Terminate the program. */
- if(signalsReceived & SIGBREAKF_CTRL_C)
- {
- BOOL terminate = FALSE;
-
- if(ShellArguments.AskExit)
- {
- UBYTE buffer[4];
-
- Printf("\nSashimi: stop signal received -- really exit (y or n)? ");
- Flush(Output());
-
- buffer[0] = '\0';
-
- if(FGets(Input(),buffer,sizeof(buffer)-1) != NULL)
- {
- if(buffer[0] == 'y' || buffer[0] == 'Y')
- terminate = TRUE;
- }
- }
- else
- {
- terminate = TRUE;
- }
-
- if(terminate)
- {
- if(RemoveSashimiResource(resource) == OK)
- {
- Printf("Sashimi removed.\n");
- done = TRUE;
- }
- }
- }
- }
- while(NOT done);
-
- RemovePatches();
-
- /* Stop the timer. */
- if(timePort != NULL)
- {
- if(CheckIO((struct IORequest *)timeRequest) == BUSY)
- AbortIO((struct IORequest *)timeRequest);
-
- WaitIO((struct IORequest *)timeRequest);
- }
-
- /* Check if we should and could save the ring buffer. */
- if(ShellArguments.AskSave && (resource->sr_FIFOWrapped || resource->sr_FIFOWriteIndex > 0))
- {
- UBYTE name[256];
-
- Printf("Enter name to save the buffer, or hit [Return] to cancel: ");
- Flush(Output());
-
- name[0] = '\0';
-
- if(FGets(Input(),name,sizeof(name)-1) != NULL)
- {
- LONG error;
- int i;
-
- for(i = strlen(name)-1 ; i >= 0 ; i--)
- {
- if(name[i] == '\n')
- name[i] = '\0';
- }
-
- error = SaveBuffer(name,resource);
- if(error == OK)
- {
- Printf("Sashimi buffer saved as \"%s\".\n",name);
- }
- else
- {
- PrintFault(error,name);
- }
- }
- }
-
- FreeSashimiResource(resource);
- resource = NULL;
- }
-
- result = RETURN_OK;
- }
-
- /* Close the resource, if we opened it. */
- if(opened)
- {
- CloseSashimiResource(resource);
- }
-
- /* Remove and free the resource if we added it. */
- if(added)
- {
- RemoveSashimiResource(resource);
- FreeSashimiResource(resource);
- }
-
- /* Clean up the timer.device interface. */
- if(timeRequest != NULL)
- {
- if(timeRequest->tr_node.io_Device != NULL)
- CloseDevice((struct IORequest *)timeRequest);
-
- DeleteIORequest((struct IORequest *)timeRequest);
- }
-
- DeleteMsgPort(timePort);
-
- /* Reset and clean up the console I/O streams. */
- if(oldOutput != NULL)
- SelectOutput(oldOutput);
-
- if(oldInput != NULL)
- SelectInput(oldInput);
-
- if(newOutput != NULL)
- Close(newOutput);
-
- if(oldConsoleTask)
- SetConsoleTask(oldConsoleTask);
-
- if(newInput != NULL)
- Close(newInput);
-
- FreeArgs(rdargs);
- }
- else
- {
- PrintFault(IoErr(),"Sashimi");
-
- result = RETURN_ERROR;
- }
- }
-
- return(result);
- }
-